/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014年7月4日
 * V4.0
 */
package com.jphenix.driver.threadpool;

import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.share.util.BaseUtil;
import com.jphenix.standard.docs.BeanInfo;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.docs.Running;
import com.jphenix.standard.threadpool.IThreadManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 线程管理类
 * com.jphenix.driver.threadpool.ThreadManager
 * 
 * 2018-12-21 增加了通过线程ID值终止指定线程
 *            增加了通过线程的HashCode终止指定线程
 * 2022-07-12 修改了内部线程容器管理机制，简化了代码
 * 
 * @author 马宝刚
 * 2014年7月4日
 */
@ClassInfo({"2024-07-25 12:40","线程管理类"})
@BeanInfo({"threadmanager","0","","","1"})
@Running({"90"})
public class ThreadManager<T extends ThreadEle<?>> extends ABase implements IThreadManager<T> {

    //线程对象序列
    private List<T> threadList = new ArrayList<T>();
    
    //线程对象容器 key线程名（不能重复）  value 线程对象
    private Map<String,T> threadMap = new HashMap<>();
    
    
    /**
     * 构造函数
     * @author 马宝刚
     */
    public ThreadManager() {
        super();
    }
    
    /**
     * 获取线程序列
     * @return 线程序列
     * 2014年7月4日
     * @author 马宝刚
     */
    @Override
    public List<T> getThreadList(){
        return threadList;
    }
    
    /**
     * 将线程元素放入管理类
     * @param ele 线程元素
     * 2014年7月4日
     * @author 马宝刚
     */
    @Override
    public boolean addThread(T ele) {
        if(ele==null || threadMap.containsKey(ele.getName()) || threadList.contains(ele)) {
            return false;
        }
        if(_beanFactory!=null && ele._beanFactory==null) {
            ele.setBase(this);
        }
        ele.setDaemon(true); //设置为守护进程，否则在进程重启时会新起一个线程，而原来的线程还在运行，成为了野线程
        threadList.add(ele);
        threadMap.put(ele.getName(),ele);
        if(!ele.isAlive()) {
            ele.start();
        }
        return true;
    }
    
    /**
     * 是否存在指定名字的线程
     * @param threadName 线程名
     * @return 是否存在指定名字的线程
     * 2022年7月12日
     * @author MBG
     */
    public boolean hasThread(String threadName) {
    	return threadMap.containsKey(threadName);
    }
    
    /**
     * 返回指定线程对象
     * @param threadName 线程名
     * @return 线程对象
     * 2022年7月12日
     * @author MBG
     */
    public T getThread(String threadName){
    	return threadMap.get(threadName);
    }
    
    /**
     * 获取所有的线程名序列
     * @return 有的线程名序列
     * 2022年7月12日
     * @author MBG
     */
    public List<String> getThreadNames(){
    	return BaseUtil.getMapKeyList(threadMap);
    }
    
    /**
     * 终止全部线程
     * 2014年7月4日
     * @author 马宝刚
     */
	@SuppressWarnings("deprecation")
	@Override
    public void stop() {
        for(ThreadEle<?> ele:threadList) {
            ele.stop();
        }
    }
    
    /**
     * 终止并移除所有线程元素
     * 2022年7月12日
     * @author MBG
     */
    public void removeAll() {
    	stop();
    	threadList.clear();
    	threadMap.clear();
    }
    
    /**
     * 终止并移除指定名称的线程对象
     * @param threadName 线程名
     * @return 移除并终止的线程对象
     * 2022年7月12日
     * @author MBG
     */
	@SuppressWarnings("deprecation")
	public T remove(String threadName) {
    	if(threadName==null || threadName.length()<1) {
    		return null;
    	}
    	T res = threadMap.remove(threadName);
    	if(res==null) {
    		return null;
    	}
    	threadList.remove(res);
    	try {
    		res.stop();
    	}catch(Exception e) {}
    	return res;
    }
    
    /**
     * 移除线程元素
     * @param thread
     * 2022年7月12日
     * @author MBG
     */
	@SuppressWarnings({ "unlikely-arg-type", "deprecation" })
	protected void removeThread(T thread) {
    	if(thread==null) {
    		return;
    	}
    	threadMap.remove(thread);
    	threadList.remove(thread);
    	try {
    		thread.stop();
    	}catch(Exception e) {}
    }
    
    
    /**
     * 干掉指定HashCode值的线程
     * @param hashCode 线程HashCode
     * 2018年12月21日
     * @author MBG
     */
    @SuppressWarnings({ "deprecation" })
    public static void killThreadByHashCode(int hashCode) {
        //获取顶级线程池
        ThreadGroup group = Thread.currentThread().getThreadGroup();  
        ThreadGroup topGroup = group;  
        //遍历线程组树，获取根线程组
        while (group != null) {  
            topGroup = group;  
            group = group.getParent();  
        } 
        //准备获取全部线程
        Thread[] threads = new Thread[topGroup.activeCount()*3]; 
        //当前线程数
        int threadCount = topGroup.enumerate(threads);
        for(int i=0;i<threadCount;i++) {
            if(threads[i]==null) {
                continue;
            }
            if(threads[i].hashCode()==hashCode) {
            	System.err.println("\n\n---Kill-Thread ID:["+threads[i].getId()+"] HashCode:["
                 +threads[i].hashCode()+"] Name:["
                 +threads[i].getName()+"] ClasPath:["+threads[i].getClass().getName()
                 +"]--by HashCode:["+hashCode+"]--\n\n");
                try {
                    threads[i].stop();
                }catch(Exception e) {}
            }
        }
    }
    
    
    /**
     * 干掉指定id的线程
     * @param id 线程ID
     * 2018年12月21日
     * @author MBG
     */
    @SuppressWarnings({ "deprecation" })
    public static void killThreadByID(long id) {
        //获取顶级线程池
        ThreadGroup group = Thread.currentThread().getThreadGroup();  
        ThreadGroup topGroup = group;  
        //遍历线程组树，获取根线程组
        while (group != null) {  
            topGroup = group;  
            group = group.getParent();  
        } 
        //准备获取全部线程
        Thread[] threads = new Thread[topGroup.activeCount()*3]; 
        //当前线程数
        int threadCount = topGroup.enumerate(threads);
        for(int i=0;i<threadCount;i++) {
            if(threads[i]==null) {
                continue;
            }
            if(threads[i].getId()==id) {
            	System.err.println("\n\n---Kill-Thread ID:["+id+"] HashCode:["+threads[i].hashCode()+"] Name:["
                 +threads[i].getName()+"] ClasPath:["+threads[i].getClass().getName()+"]--by ID:["+id+"]--\n\n");
                try {
                    threads[i].stop();
                }catch(Exception e) {}
            }
        }
    }
    
    
    /**
     * 干掉指定关键字开头类名的线程
     * @param classNameKey 指定关键字（类开头名字，用来获取起内部线程类）
     * 2015年8月14日
     * @author 马宝刚
     */
    @SuppressWarnings({ "deprecation" })
    public static void killThreadByClassNameKey(String classNameKey) {
        //获取顶级线程池
        ThreadGroup group = Thread.currentThread().getThreadGroup();  
        ThreadGroup topGroup = group;  
        //遍历线程组树，获取根线程组
        while (group != null) {  
            topGroup = group;  
            group = group.getParent();  
        } 
        //准备获取全部线程
        Thread[] threads = new Thread[topGroup.activeCount()*3]; 
        //当前线程数
        int threadCount = topGroup.enumerate(threads);
        //线程类名
        String threadClassName;
        for(int i=0;i<threadCount;i++) {
            if(threads[i]==null) {
                continue;
            }
            threadClassName = threads[i].getClass().getName();
            if(threadClassName.startsWith(classNameKey)) {
            	System.err.println("\n\n---Kill-Thread ID:["+threads[i].getId()+"] HashCode:["+threads[i].hashCode()+"] Name:["
                        +threads[i].getName()+"] ClasPath:["+threads[i].getClass().getName()+"]--by Name:["+classNameKey+"]--\n\n");
                try {
                    threads[i].stop();
                }catch(Exception e) {}
            }
        }
    }
}
